package com.hello915.googledirectionapi.utils;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;

import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.Polyline;
import com.google.android.gms.maps.model.PolylineOptions;
import com.hello915.googledirectionapi.R;
import com.hello915.googledirectionapi.route.result.Route;

import android.location.Location;

/**
 * 地图实用工具，添加Marker，改变地图中心（添加其他覆盖物等，还没写）
 * @author Dorian
 *
 */
public class MapUtil {

	private GoogleMap map;
	private AnimateConfig aConfig;

	public MapUtil(GoogleMap map){
		this.map = map;
		aConfig = new AnimateConfig();
	}
	
	/**
	 * 动画形式将地图中心移动到指定点
	 * @param latlng 指定的中心
	 */
	public void moveToCenter(LatLng latlng, AnimateConfig acon){
		if(latlng == null){
			return;
		}
		AnimateConfig ani = null;
		if(acon != null){
			ani = acon;
		}else{
			ani = aConfig;
		}
		CameraPosition cameraPosition = new CameraPosition.Builder()
				.target(latlng)
				.zoom(ani.zoomLevel)
				.bearing(ani.bearing)     // Sets the orientation of the camera to east
				.tilt(ani.tilt)         // Sets the tilt(倾斜) of the camera to 30 degrees
				.build();
		CameraUpdate update = CameraUpdateFactory.newCameraPosition(cameraPosition);
		map.animateCamera(update);
	}
	
	/**
	 * 
	 * @param location
	 * @param acon 为null则使用默认的配置
	 */
	public void moveToCenter(Location location, AnimateConfig acon){
		if(location == null){
			return;
		}
		if(acon == null){
			acon = this.aConfig;
		}
		LatLng ll = new LatLng(location.getLatitude()
				, location.getLongitude());
		moveToCenter(ll, acon);
	}
	
	/**
	 * 
	 * @param lat
	 * @param lng
	 * @param acon 为null则使用默认的配置
	 */
	public void moveToCenter(double lat, double lng, AnimateConfig acon){
		if(acon == null){
			acon = this.aConfig;
		}
		LatLng ll = new LatLng(lat, lng);
		moveToCenter(ll, acon);
	}

	/**
	 * 添加一个Marker，参数最全，自行配置
	 * @param ll        坐标
	 * @param title     标题
	 * @param snippet   描述小段文字   
	 * @param resId     Marker图标
	 * @param flat      是否贴着地面（贴着则跟着地面转动）
	 * @param draggable 能否拖动
	 * @param alpha     透明度
	 * @return
	 */
	public Marker addMarker(LatLng ll, String title, String snippet, 
			int resId, boolean flat, boolean draggable, float alpha){
		if(ll == null)
			return null;
		MarkerOptions mo = new MarkerOptions();
		mo.position(ll)
		.title(title)
		.snippet(snippet)
		.alpha(alpha)
		.draggable(draggable)
		.flat(flat)
		.icon(BitmapDescriptorFactory.fromResource(resId));
		return map.addMarker(mo);
	}

	/**
	 * 添加一个一个Marker，可拖动，不随地图转动，完全不透明
	 * @param ll
	 * @param title
	 * @param snippet
	 * @param resId
	 * @return
	 */
	public Marker addMarker(LatLng ll, String title, String snippet, int resId){
		return addMarker(ll, title, snippet,resId, false, true,1.0f);
	}

	/**
	 * 添加一个蓝色图标的Marker，可拖动，不随地图转动，完全不透明
	 * @param ll
	 * @param title
	 * @param snippet
	 * @return
	 */
	public Marker addMarker(LatLng ll, String title, String snippet){
		return addMarker(ll,title,snippet,R.drawable.location_blue_50x74);
	}

	/**
	 * 将一个Marker添加到地图，因为GoogleMap没有直接添加Marker的接口
	 * 所以在刷新地图的时候只能重新调用接口绘制一次Marker，
	 * @param marker
	 * @param resId
	 * @return
	 */
	public void addMarker(Marker marker, int resId){
		if(marker == null){
			return ;
		}
		LatLng ll = marker.getPosition();
		String title = marker.getTitle();
		String snept = marker.getSnippet();
		boolean flat = marker.isFlat();
		boolean draggable = marker.isDraggable();
		float alpha = marker.getAlpha();
		addMarker(ll,title,snept,resId,flat,draggable,alpha);
	}
	
	/**
	 * 
	 * @param markerMap
	 * @param resId
	 */
	public void addMarkers(HashMap<String,Marker> markerMap, int resId){
		if(markerMap == null){
			return;
		}
		for(String key : markerMap.keySet()){
			addMarker(markerMap.get(key), resId);
		}
	}
	
	public void clearMarkers(HashMap<String,Marker> markerMap){
		if(markerMap == null){
			return;
		}
		for(String key : markerMap.keySet()){
			markerMap.get(key).remove();
		}
	}
	/**
	 * 改变地图中心动画参数配置
	 * @author Dorian
	 *
	 */
	public class AnimateConfig{
		
		public int zoomLevel;     
		public float bearing;
		public float tilt;
		
		public AnimateConfig(){
			this.zoomLevel = 17;
			this.bearing = 0f;
			this.tilt = 0f;
		}
		
		public AnimateConfig(int zoomLevel, float bearing,float tilt){
			this.zoomLevel = zoomLevel;
			this.bearing = bearing;
			this.tilt = tilt;
		}
	}

	/**
	 * 添加一条线，由一组有序的点相连，google提供的接口很有限，只能设置个颜色
	 * @param points 途经点
	 * @param color 线的颜色
	 * @return
	 */
	public Polyline addPolyline(List<LatLng> points, int color){
		if(points == null || points.size() < 1){
			return null;
		}
		PolylineOptions po = new PolylineOptions();
		Iterator<LatLng> it = points.iterator();
		while(it.hasNext()){
			po.add(it.next());
		}
		po.color(color);
		return map.addPolyline(po);
	}
	
	/**
	 * 添加一条线，由Google Direction Api返回的Route提供有序的点
	 * @param route 
	 * @param color
	 * @return
	 */
	public Polyline addPolyline(Route route, int color){
		if(route == null || route.overview_polyline == null){
			return null;
		}
		return addPolyline(route.overview_polyline.getWayPoint(), color);
	}

	/**
	 * 获取一组点的矩形区域，返回格式为安照：东南西北的顺序。
	 * 如果传入来的点数少于2则返回一个null;
	 * 求中心点坐标只需要分别对应相加求和，再取平均就可以了
	 * @param points
	 * @return
	 */
	public double[] getBounds(List<LatLng> points){
		if(points == null || points.size() < 2){
			return null;
		}
		LatLng temp = points.get(0);
		double[] bounds = new double[]{temp.longitude,
				temp.latitude, temp.longitude, temp.latitude};
		for(int i = 1; i < points.size(); i++){
			temp = points.get(i);
			if(temp.longitude > bounds[0]){
				bounds[0] = temp.longitude;
			}else if(temp.longitude < bounds[2]){
				bounds[2] = temp.longitude;
			}
			if(temp.latitude > bounds[3]){
				bounds[3] = temp.latitude;
			}else if(temp.latitude < bounds[1]){
				bounds[1] = temp.latitude;
			}
		}
		return bounds;
	}
	
	/**
	 * 获取给点坐标点数组的外接矩形，
	 * @param points
	 * @return
	 */
	public LatLngBounds getLatLngBounds(List<LatLng> points){
		double[] bounds = this.getBounds(points);
		if(bounds == null){
			return null;
		}
		LatLng southwest = new LatLng(bounds[1], bounds[2]);
		LatLng northeast = new LatLng(bounds[3], bounds[0]);
		LatLngBounds llbs = new LatLngBounds(southwest, northeast);
		return llbs;
	}
	
	/**
	 * 地图显示区域移动到指定的矩形
	 * @param bounds
	 * @param padding 外接矩形与地图容器间的距离单位px
	 */
	public void moveToBounds(LatLngBounds bounds, int padding){
		CameraUpdate update = CameraUpdateFactory.newLatLngBounds(bounds, padding);
		map.animateCamera(update);
	}
	
	/**
	 * 地图显示区域移动到指定的一组坐标点的外接矩形范围
	 * @param points
	 * @param padding 外接矩形与地图容器间的距离单位px
	 */
	public void moveToBounds(List<LatLng> points, int padding){
		LatLngBounds bounds = getLatLngBounds(points);
		this.moveToBounds(bounds, padding);
	}
}









